package com.cskaoyan.utils;


import java.lang.reflect.*;
import java.util.*;

/**
 * @author:jiangsonglin.com
 */

public class PojoUtils {
    public static Converter converter() {
        return new PojoConverter();
    }

    private static class PojoConverter implements Converter {

        private HashMap<String, String> nameMap = new HashMap<>();

        @Override
        public HashMap<String, String> setName(String formName, String destName) {
            nameMap.put(destName, formName);  // oderName,orderVoName
            return nameMap;
        }

        @Override
        public <T, V> V converter(T from, V to) {
            // key  class
            HashMap<String, Class> map = new HashMap<>();

            Class<?> fromClass = from.getClass();
            Class<?> toClass = to.getClass();
            Field[] fields = toClass.getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                String name = field.getName(); // orderVoName
//                String destName = nameMap.get(name);
//                if (destName != null) {
//                    name = destName; // getUserId,setUserIds
//                }

                Class<?> type = field.getType();
                map.put(captureName(name), type); //userIds
            }
            // all fields name
            Set<String> set = map.keySet();
            Iterator<String> iterator = set.iterator();
            while (iterator.hasNext()) {
                String destMethodName = iterator.next(); // UserIds
                Object invoke = null;
                String lowerName = lowerName(destMethodName);
                // isReg
                String formName = nameMap.get(lowerName);
                String finalMethodName = formName==null
                        ?destMethodName: captureName(formName);
                try {
                    try {
                        Method getMethod = fromClass.getDeclaredMethod("get" + finalMethodName);
                        invoke = getMethod.invoke(from);
                    } catch (NoSuchMethodException e) {
                        e.printStackTrace();
                        System.out.println(finalMethodName + "没有找到");
                        String typeName = map.get(destMethodName).getName();
                        if (typeName.equals("boolean") || typeName.equals(Boolean.class.getName())) {
                            Method getMethod = fromClass.getDeclaredMethod("is" + finalMethodName);
                            invoke = getMethod.invoke(from);
                        }
                    }
                    if (invoke != null) {
                        // get到值 开始注入vo
                        Method setMethod = toClass.getDeclaredMethod("set" + destMethodName, map.get(destMethodName));


                        setMethod.invoke(to, new Object[]{invoke});
                    }
                } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | IllegalArgumentException e) {
                    System.err.println("调用" + destMethodName + "相关方法出现错误！,请检查参数类型是否正确或者方法是否存在！！！");
                    e.printStackTrace();
                }
            }
            return to;
        }

        /**
         * 将字符串的首字母转大写
         *
         * @param str 需要转换的字符串
         * @return
         */
        private String captureName(String str) {
            // 进行字母的ascii编码前移，效率要高于截取字符串进行转换的操作
            char[] cs = str.toCharArray();
            cs[0] -= 32;
            return String.valueOf(cs);
        }
        private String lowerName(String str) {
            // 进行字母的ascii编码前移，效率要高于截取字符串进行转换的操作
            char[] cs = str.toCharArray();
            cs[0] += 32;
            return String.valueOf(cs);
        }
        @Override
        public <T, V> List<V> listConverter(List<T> formList, List<V> toList, Class<?> toClazz) {

            for (T item : formList) {
                try {
                    Object o = toClazz.newInstance();
                    V v = (V) o;
                    this.converter(item, v);
                    toList.add(v);
                } catch (InstantiationException | IllegalAccessException e) {
                    e.printStackTrace();
                    System.err.println("实例化失败！");
                }

            }
            return toList;
        }

        private <V> Type getGenericType(List<V> toList) {
            Class<? extends List> listClass = toList.getClass();
            Field[] fields = listClass.getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                Type genericType = field.getGenericType();
                if (genericType == null) continue;
                if (genericType instanceof ParameterizedType) {
                    ParameterizedType type = (ParameterizedType) genericType;
                    return type.getActualTypeArguments()[0];
                }
            }
            return null;
        }

    }
}
